/**
 * Title:		KFrogBuiltInFunctions.java
 * Description: This class is responsible for all the built-in functions. 
 * 
 * @version		1.0 May 2009
 * @author		Rami Habas
 */

package kfrog;

import java.util.Hashtable;
import kfrog.type.*;


public class KFrogBuiltInFunctions {

	/** the following are used for internal id's */
	private final static int RANDOM = 0;
	private final static int SQRT = 1;

	/** useful debug message */
	private static void debug(String message) {
		if (KFrogMain.debug)
			System.out.println(message);
	}

	/**
     * Registers all built-in functions by adding an entry in the given 
     * hashtable.
     * 
     * @param functionTable   The hashtable that stores all the functions
     */
	public static void register(Hashtable<String,KFrogFunction> functionTable) {
		register(functionTable, "random", RANDOM);
		register(functionTable, "sqrt", SQRT);
	}

	/**
     * Adds the built-in function to the given hashtable. The built-in function 
     * is distinguished by its name and internal id.
     * 
     * @param functionTable   The hashtable that stores all the functions
     * @param name            The function name
     * @param id              The internal function id
     */
	private static void register(Hashtable<String,KFrogFunction> functionTable,
			String name, int id) {
		KFrogFunction function = new KFrogFunction(name, getArgs(id), id);
		functionTable.put(function.getSignature(), function);
		if (KFrogMain.debug)
			System.out.println("Registered built-in function: " + 
					function.getSignature());
	}

	/**
     * Returns an array of the formal parameter data types for the built-in
     * function with the given id.
     * 
     * @param id   The internal function id
     */
	private static KFrogDataType[] getArgs(int id) {
		KFrogDataType[] args;

		if(id == RANDOM) {
			args = new KFrogDataType[2];
			args[0] = new KFrogDecimal();
			args[1] = new KFrogDecimal();
		}
		else if(id == SQRT) {
			args = new KFrogDataType[1];
			args[0] = new KFrogReal();
		}
		else {
			throw new RuntimeException("The built-in function with id="+id +
					" does not exist");
		}

		return args;
	}
	
	/**
     * Executes the function call and returns a value.
     * 
     * @param function   The built-in function to execute
     * @param args       The actual parameters
     */
	public static KFrogDataType call(KFrogFunction function,
			KFrogDataType[] args) {
		String message = function.getSignature();
		int m, n, result;
		double a, r;

		if(function.getId()== RANDOM) {
			debug(message);
			m = KFrogDecimal.decimalValue(args[0]);
			n = KFrogDecimal.decimalValue(args[1]);
			result = (int)Math.floor(Math.random() * (n - m + 1)) + m;
			return new KFrogDecimal(result);
		}
		else if(function.getId()== SQRT) {
			debug(message);
			a = KFrogReal.realValue(args[0]);
			r = Math.sqrt(a);
			return new KFrogReal(r);
		}
		else {
			throw new RuntimeException("The built-in function with id=" +
					function.getId() + " does not exist");
		}
	}
}
